package org.microframework.cloud.files.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.microframework.cloud.files.model.ApiResponse;
import org.microframework.cloud.files.model.FileInfo;
import org.microframework.cloud.files.service.MinioFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 文件管理控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/files")
@Tag(name = "文件管理", description = "文件上传、下载、删除等操作")
public class FileController {

    private final MinioFileService fileService;

    @Autowired
    public FileController(MinioFileService fileService) {
        this.fileService = fileService;
    }

    /**
     * 上传文件
     */
    @PostMapping("/upload")
    @Operation(summary = "上传文件", description = "上传文件到指定目录，支持公共/私有访问模式")
    public ApiResponse<FileInfo> uploadFile(
            @Parameter(description = "文件") @RequestParam("file") MultipartFile file,
            @Parameter(description = "是否公开访问") @RequestParam(value = "public", defaultValue = "false") boolean isPublic,
            @Parameter(description = "目录路径") @RequestParam(value = "directory", required = false) String directory) {
        log.info("上传文件: {}, 公开: {}, 目录: {}", file.getOriginalFilename(), isPublic, directory);
        FileInfo fileInfo = fileService.uploadFile(file, isPublic, directory);
        return ApiResponse.success(fileInfo);
    }

    /**
     * 批量上传文件
     */
    @PostMapping("/batch-upload")
    @Operation(summary = "批量上传文件", description = "批量上传文件到指定目录")
    public ApiResponse<List<FileInfo>> batchUploadFiles(
            @Parameter(description = "文件列表") @RequestParam("files") MultipartFile[] files,
            @Parameter(description = "是否公开访问") @RequestParam(value = "public", defaultValue = "false") boolean isPublic,
            @Parameter(description = "目录路径") @RequestParam(value = "directory", required = false) String directory) {
        log.info("批量上传文件: {} 个, 公开: {}, 目录: {}", files.length, isPublic, directory);
        
        List<FileInfo> fileInfos = new ArrayList<>();
        for (MultipartFile file : files) {
            FileInfo fileInfo = fileService.uploadFile(file, isPublic, directory);
            fileInfos.add(fileInfo);
        }
        
        return ApiResponse.success(fileInfos);
    }

    /**
     * 下载文件
     */
    @GetMapping("/download/{fileId}")
    @Operation(summary = "下载文件", description = "根据文件ID下载文件")
    public ResponseEntity<ByteArrayResource> downloadFile(
            @Parameter(description = "文件ID") @PathVariable String fileId) {
        log.info("下载文件: {}", fileId);
        
        FileInfo fileInfo = fileService.getFileInfoById(fileId);
        byte[] data = fileService.downloadFile(fileId);
        
        String encodedFilename = URLEncoder.encode(fileInfo.getOriginalFilename(), StandardCharsets.UTF_8)
                .replace("+", "%20");
        
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(fileInfo.getContentType()))
                .contentLength(data.length)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFilename)
                .body(new ByteArrayResource(data));
    }

    /**
     * 获取文件信息
     */
    @GetMapping("/{fileId}")
    @Operation(summary = "获取文件信息", description = "根据文件ID获取文件详细信息")
    public ApiResponse<FileInfo> getFileInfo(
            @Parameter(description = "文件ID") @PathVariable String fileId) {
        log.info("获取文件信息: {}", fileId);
        FileInfo fileInfo = fileService.getFileInfoById(fileId);
        return ApiResponse.success(fileInfo);
    }

    /**
     * 删除文件
     */
    @DeleteMapping("/{fileId}")
    @Operation(summary = "删除文件", description = "根据文件ID删除文件")
    public ApiResponse<Boolean> deleteFile(
            @Parameter(description = "文件ID") @PathVariable String fileId) {
        log.info("删除文件: {}", fileId);
        boolean result = fileService.deleteFile(fileId);
        return ApiResponse.success(result);
    }

    /**
     * 批量删除文件
     */
    @DeleteMapping("/batch")
    @Operation(summary = "批量删除文件", description = "批量删除文件")
    public ApiResponse<List<String>> batchDeleteFiles(
            @Parameter(description = "文件ID列表") @RequestBody List<String> fileIds) {
        log.info("批量删除文件: {}", fileIds);
        List<String> failedFiles = fileService.batchDeleteFiles(fileIds);
        return ApiResponse.success(failedFiles);
    }

    /**
     * 获取预签名URL
     */
    @GetMapping("/presigned-url/{fileId}")
    @Operation(summary = "获取预签名URL", description = "获取文件的临时访问URL")
    public ApiResponse<String> getPresignedUrl(
            @Parameter(description = "文件ID") @PathVariable String fileId,
            @Parameter(description = "过期时间(小时)") @RequestParam(value = "expiryHours", required = false) Integer expiryHours) {
        log.info("获取预签名URL: {}, 过期时间: {}", fileId, expiryHours);
        String url = fileService.getPresignedUrlByFileId(fileId, expiryHours);
        return ApiResponse.success(url);
    }

    /**
     * 列出文件
     */
    @GetMapping("/list")
    @Operation(summary = "列出文件", description = "列出指定目录下的文件")
    public ApiResponse<List<FileInfo>> listFiles(
            @Parameter(description = "目录路径") @RequestParam(value = "directory", required = false) String directory,
            @Parameter(description = "是否查询公共存储桶") @RequestParam(value = "public", defaultValue = "false") boolean isPublic) {
        log.info("列出文件, 目录: {}, 公开存储桶: {}", directory, isPublic);
        List<FileInfo> files = fileService.listFiles(directory, isPublic);
        return ApiResponse.success(files);
    }
}